#pragma once

#include <string>
#include <memory>
// opencv
// #include <opencv2/core/core.hpp>
#include "cv_mat.hpp"
#include "FFTTools.hpp"

class TrackerKCF
{
public:

    TrackerKCF(int patch_size = 128, bool multiscale = true);

    ~TrackerKCF();

    // Update tracker based on the object's ROI and new frame data
    void update(const CvRect& src_roi, CvMatU8 &src_image, float train_interp_factor);

    // Detect object in the current frame
    CvRect detect(const CvRect& dst_roi, CvMatU8 & dst_image, float& peak_value);
    uint8_t *debug_buf;
protected:
    CvPoint2f findPixelPeak(CvMat_hfq15 &z, CvMat_hfq15 &x, float& peak_value);

    void adjustROI(const CvRect &roi, CvMatU8 &image);

    // Evaluates a Gaussian kernel with bandwidth SIGMA for all relative shifts between input images X and Y,
    // which must both be MxN. They must also be periodic (ie., pre-processed with a cosine window).
    CvMat_hfq15 gaussianCorrelation(CvMat_hfq15 & x1, CvMat_hfq15 & x2);

    // Obtain sub-window from image, with replication-padding and extract features.
    CvMat_hfq15 getFeatures(const CvMatU8& image, float scale_adjust = 1.f);

    // Calculate sub-pixel peak for one dimension.
    float subPixelPeak(float left, float center, float right);

    // Initialize Hanning window. Function called only in TrackerKCF constructor.
    void createHanningMats();

    // Create Gaussian Peak. Function called only in TrackerKCF constructor.
    void createGaussianPeak();

    wfq15_t _neg_sigma2; // Q15
    int _patch_size;
    float _sigma;
    float _output_sigma_factor;
    wfq16_t _lambda;  // Q15
    float _padding;
    float _scale;
    float _scale_step;
    float _scale_weight;

    CvMat_cwfq16 _alphaf; // 
    CvMat_hfq15 _tmpl; // Q15
    CvMat_cwfq16 _prob; // 128--->Q15.16 // Q<2*log2(n)+1>.<31-(2*log2(n)+1)>
    CvMat_hfq15 _hann;  // Q15 

    CvRectf _roi;
    CvRectf _pad_roi;

    FFT_HVX _fft;
};
